<!DOCTYPE html>
<html class="writer-html5" lang="zh" >
<head>
  <meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Ch3-6 描述符 &mdash; EasyVulkan</title>
      <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
      <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
      <link rel="stylesheet" href="_static/theme.css" type="text/css" />
  <!--[if lt IE 9]>
    <script src="_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
        <script src="_static/jquery.js"></script>
        <script src="_static/underscore.js"></script>
        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
        <script src="_static/doctools.js"></script>
    <script src="_static/js/theme.js"></script>
    <link rel="index" title="索引" href="genindex.html" />
    <link rel="search" title="搜索" href="search.html" />
    <link rel="next" title="Ch3-7 采样器" href="Ch3-7%20%E9%87%87%E6%A0%B7%E5%99%A8.html" />
    <link rel="prev" title="Ch3-5 命令缓冲区" href="Ch3-5%20%E5%91%BD%E4%BB%A4%E7%BC%93%E5%86%B2%E5%8C%BA.html" /> 
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
            <a href="index.html" class="icon icon-home"> EasyVulkan
            <img src="_static/logo1.png" class="logo" alt="Logo"/>
          </a>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
    <input type="text" name="q" placeholder="在文档中搜索" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
              <p class="caption" role="heading"><span class="caption-text">第一章 初始化</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch1-0%20%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C.html">Ch1-0 准备工作</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-1%20%E5%88%9B%E5%BB%BAGLFW%E7%AA%97%E5%8F%A3.html">Ch1-1 创建GLFW窗口</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-2%20%E5%88%9D%E5%A7%8B%E5%8C%96%E6%B5%81%E7%A8%8B.html">Ch1-2 初始化流程</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-3%20%E5%88%9B%E5%BB%BAVK%E5%AE%9E%E4%BE%8B%E4%B8%8E%E9%80%BB%E8%BE%91%E8%AE%BE%E5%A4%87.html">Ch1-3 创建VK实例与逻辑设备</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-4%20%E5%88%9B%E5%BB%BA%E4%BA%A4%E6%8D%A2%E9%93%BE.html">Ch1-4 创建交换链</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第二章 绘制一个三角形</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch2-0%20%E4%BB%A3%E7%A0%81%E6%95%B4%E7%90%86%E5%8F%8A%E4%B8%80%E4%BA%9B%E8%BE%85%E5%8A%A9%E7%B1%BB.html">Ch2-0 代码整理及一些辅助类</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-1%20Rendering%20Loop.html">Ch2-1 Rendering Loop</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-2%20%E5%88%9B%E5%BB%BA%E6%B8%B2%E6%9F%93%E9%80%9A%E9%81%93%E5%92%8C%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch2-2 创建渲染通道和帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-3%20%E5%88%9B%E5%BB%BA%E7%AE%A1%E7%BA%BF%E5%B9%B6%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2.html">Ch2-3 创建管线并绘制三角形</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第三章 纵观Vulkan</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Ch3-1%20%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD.html">Ch3-1 同步原语</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-2%20%E5%9B%BE%E5%83%8F%E4%B8%8E%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch3-2 图像与缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-3%20%E7%AE%A1%E7%BA%BF%E5%B8%83%E5%B1%80%E5%92%8C%E7%AE%A1%E7%BA%BF.html">Ch3-3 管线布局和管线</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-4%20%E6%B8%B2%E6%9F%93%E9%80%9A%E9%81%93%E5%92%8C%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch3-4 渲染通道和帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-5%20%E5%91%BD%E4%BB%A4%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch3-5 命令缓冲区</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Ch3-6 描述符</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#id1">描述符类型</a></li>
<li class="toctree-l2"><a class="reference internal" href="#descriptor-set-layout">Descriptor Set Layout</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#id2">创建描述符布局</a></li>
<li class="toctree-l3"><a class="reference internal" href="#descriptorsetlayout">封装为descriptorSetLayout类</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#descriptor-set">Descriptor Set</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#id3">更新描述符集</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#id4">写入描述符集</a></li>
<li class="toctree-l4"><a class="reference internal" href="#id5">复制描述符集</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#descriptorset">封装为descriptorSet类</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#descriptor-pool">Descriptor Pool</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#id6">创建描述符池</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id7">分配描述符集</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id8">释放描述符集</a></li>
<li class="toctree-l3"><a class="reference internal" href="#descriptorpool">封装为descriptorPool类</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-7%20%E9%87%87%E6%A0%B7%E5%99%A8.html">Ch3-7 采样器</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-8%20%E6%9F%A5%E8%AF%A2.html">Ch3-8 查询</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第四章 着色器</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch4-1%20%E7%9D%80%E8%89%B2%E5%99%A8%E6%A8%A1%E7%BB%84.html">Ch4-1 着色器模组</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch4-2%20%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8.html">Ch4-2 顶点着色器</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch4-3%20%E7%89%87%E6%AE%B5%E7%9D%80%E8%89%B2%E5%99%A8.html">Ch4-3 片段着色器</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch4-4%20%E5%87%A0%E4%BD%95%E7%9D%80%E8%89%B2%E5%99%A8.html">Ch4-4 几何着色器</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第五章 封装常用对象</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch5-0%20VKBase%2B.h.html">Ch5-0 VKBase+.h</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-1%20%E5%90%84%E7%A7%8D%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch5-1 各种缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-2%202D%E8%B4%B4%E5%9B%BE%E5%8F%8A%E7%94%9F%E6%88%90Mipmap.html">Ch5-2 2D贴图及生成Mipmap</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-3%202D%E8%B4%B4%E5%9B%BE%E6%95%B0%E7%BB%84.html">Ch5-3 2D贴图数组</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第六章 进阶Vulkan</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch6-0%20%E4%BD%BF%E7%94%A8%E6%96%B0%E7%89%88%E6%9C%AC%E7%89%B9%E6%80%A7.html">Ch6-0 使用新版本特性</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch6-1%20%E6%97%A0%E5%9B%BE%E5%83%8F%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch6-1 无图像帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch6-2%20%E5%8A%A8%E6%80%81%E6%B8%B2%E6%9F%93.html">Ch6-2 动态渲染</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第七章 基础示例</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch7-1%20%E5%88%9D%E8%AF%86%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-1 初识顶点缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-2%20%E5%88%9D%E8%AF%86%E7%B4%A2%E5%BC%95%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-2 初识索引缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-3%20%E5%88%9D%E8%AF%86%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%BB%98%E5%88%B6.html">Ch7-3 初识实例化绘制</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-4%20%E5%88%9D%E8%AF%86Push%20Constant.html">Ch7-4 初识Push Constant</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-5%20%E5%88%9D%E8%AF%86Uniform%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-5 初识Uniform缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-6%20%E6%8B%B7%E8%B4%9D%E5%9B%BE%E5%83%8F%E5%88%B0%E5%B1%8F%E5%B9%95.html">Ch7-6 拷贝图像到屏幕</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-7%20%E4%BD%BF%E7%94%A8%E8%B4%B4%E5%9B%BE.html">Ch7-7 使用贴图</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第八章 简单示例</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch8-1%20%E7%A6%BB%E5%B1%8F%E6%B8%B2%E6%9F%93.html">Ch8-1 离屏渲染</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-2%20%E6%B7%B1%E5%BA%A6%E6%B5%8B%E8%AF%95%E5%92%8C%E6%B7%B1%E5%BA%A6%E5%8F%AF%E8%A7%86%E5%8C%96.html">Ch8-2 深度测试和深度可视化</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-3%20%E5%BB%B6%E8%BF%9F%E6%B8%B2%E6%9F%93.html">Ch8-3 延迟渲染</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-4%20%E9%A2%84%E4%B9%98Alpha.html">Ch8-4 预乘Alpha</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-5%20sRGB%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4%E4%B8%8E%E5%BC%80%E5%90%AFHDR.html">Ch8-5 sRGB色彩空间与开启HDR</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">附录</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ap1-1%20%E8%BF%90%E8%A1%8C%E6%9C%9F%E7%BC%96%E8%AF%91GLSL.html">Ap1-1 运行期编译GLSL</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="index.html">EasyVulkan</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="index.html" class="icon icon-home"></a> &raquo;</li>
      <li>Ch3-6 描述符</li>
      <li class="wy-breadcrumbs-aside">
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section id="ch3-6">
<h1>Ch3-6 描述符<a class="headerlink" href="#ch3-6" title="Permalink to this heading"></a></h1>
<p>
    描述符（descriptor）是用于描述着色器中所使用的资源（缓冲区、贴图、采样器）的一种不透明数据类型。
    <br>
    在使用描述符时以描述符集的形式（<span class="type">VkDescriptorSet</span>）是成套使用的，描述符集则从描述符池（<span class="type">VkDescriptorPool</span>）中分配。
    <br>
    管线必须具有相应的描述符布局（<span class="type">VkDescriptorSetLayout</span>）才能绑定相应描述符集。
</p><section id="id1">
<h2>描述符类型<a class="headerlink" href="#id1" title="Permalink to this heading"></a></h2>
<p>
    描述符有以下类型：
</p>
<table class="docutils align-default">
    <colgroup>
        <col>
        <col>
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head"><p>版本要求</p></th>
            <th class="head"><p><a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorType">VkDescriptorType</a> 的枚举项</p></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_SAMPLER                </span>表示采样器</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER </span>表示带采样器的被采样图像</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE          </span>表示被采样图像</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_STORAGE_IMAGE          </span>表示storage图像（任意着色器可读，可在计算着色器中进行写入）</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER   </span>表示uniform纹素缓冲区（着色器中只读）</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER   </span>表示storage纹素缓冲区（任意着色器可读，可在计算着色器中进行写入）</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER         </span>表示uniform缓冲区（在着色器中只读）</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_STORAGE_BUFFER         </span>表示storage缓冲区（可在任意着色器中指定其可读写性）</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC </span>表示动态uniform缓冲区</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC </span>表示动态storage缓冲区</p></td>
        </tr>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT       </span>表示输入附件</p></td>
        </tr>
        <tr>
            <td><p>1.3</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK   </span>表示内联uniform块</p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            在<strong>写入</strong>描述符时，可以指定uniform缓冲区和storage缓冲区的offset，而动态uniform缓冲区和动态storage缓冲区是在此基础上，在<strong>绑定</strong>时，可以再多指定一个offset的缓冲区。这意味着，你可以将多个具有同类数据的uniform/storage缓冲区放进单个动态uniform/storage缓冲区中，然后在绑定时指定不同的offset来使用。
        </p>
    </li>
    <li>
        <p>
            内联uniform块不需要缓冲区，而是能通过使得<a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkWriteDescriptorSet">VkWriteDescriptorSet</a>的pNext指向一个<a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkWriteDescriptorSetInlineUniformBlock">VkWriteDescriptorSetInlineUniformBlock</a>结构体，在写入描述符时直接更新内联uniform块的数据，适用于少量数据。相比push constant，适合不会经常变更的数据。
        </p>
    </li>
    <li>
        <p>
            通过开启硬件特性中的vertexPipelineStoresAndAtomics和fragmentStoresAndAtomics，可在其他图形管线阶段写入storage图像和storage纹素缓冲区。
        </p>
    </li>
</ul></section>
<section id="descriptor-set-layout">
<h2>Descriptor Set Layout<a class="headerlink" href="#descriptor-set-layout" title="Permalink to this heading"></a></h2>
<p>
    描述符布局（<span class="type">VkDescriptorSetLayout</span>）包含了管线如何使用描述符的信息。
</p><section id="id2">
<h3>创建描述符布局<a class="headerlink" href="#id2" title="Permalink to this heading"></a></h3>
<p>
    用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkCreateDescriptorSetLayout">vkCreateDescriptorSetLayout</a>(...)创建描述符布局：
</p>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="type">VkResult</span> <span class="mcr">VKAPI_CALL</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkCreateDescriptorSetLayout">vkCreateDescriptorSetLayout</a>(...) 的参数说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDevice</span> device</p></td>
            <td><p>逻辑设备的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorSetLayoutCreateInfo</span>* pCreateInfo</p></td>
            <td><p>指向<span class="type">VkDescriptorSetLayout</span>的创建信息</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkAllocationCallbacks</span>* pAllocator</p></td>
            <td><p></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDescriptorSetLayout</span>* pSetLayout</p></td>
            <td><p>若执行成功，将描述符布局的handle写入*pSetLayout</p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorSetLayoutCreateInfo">VkDescriptorSetLayoutCreateInfo</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkStructureType</span> sType</p></td>
            <td><p>结构体的类型，本处必须是<span class="enum">VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const void</span>* pNext</p></td>
            <td><p>如有必要，指向一个用于扩展该结构体的结构体</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorSetLayoutCreateFlags</span> flags</p></td>
            <td><p>见后文</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> bindingCount</p></td>
            <td><p><span class="type">VkDescriptorSetLayoutBinding</span>的个数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorSetLayoutBinding</span>* pBindings</p></td>
            <td><p>指向<span class="type">VkDescriptorSetLayoutBinding</span>的数组，用于指定着色器中各个binding所对应的描述符类型</p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            若flags中包含<span class="enum">VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT</span>（需Vulkan1.2），则需要使得pNext指向一个<a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorSetLayoutBindingFlagsCreateInfo">VkDescriptorSetLayoutBindingFlagsCreateInfo</a>结构体并指定<span class="enum">VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT</span>，以及在创建相应描述符池时，也应该注明<span class="enum">VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT</span>（见后文“更新描述符集”）。
        </p>
    </li>
</ul>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorSetLayoutBinding">VkDescriptorSetLayoutBinding</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> binding</p></td>
            <td><p>对应着色器中的binding</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDescriptorType</span> descriptorType</p></td>
            <td><p>描述符类型</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> descriptorCount</p></td>
            <td><p>描述符的个数（描述符可以构成数组），或uniform块的容量（仅限<span class="enum">VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK</span>）</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkShaderStageFlags</span> stageFlags</p></td>
            <td><p>会访问本结构体指定的描述符的阶段</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkSampler</span>* pImmutableSamplers</p></td>
            <td><p>用于指定不可变更的采样器，见后文</p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            若描述符类型为<span class="enum">VK_DESCRIPTOR_TYPE_SAMPLER</span>或<span class="enum">VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</span>，则用pImmutableSamplers指定descriptorCount个不可变更的采样器，无需指定则pImmutableSamplers为<span class="kw">nullptr</span>。
        </p>
    </li>
</ul>
<p>
    不可变更的采样器的具体效果是：
    <br>
    pImmutableSamplers所指向的一系列采样器的handle被保存到描述符布局中，使得相应binding的采样器一直是所指定的采样器（之后无需也不可再更新），若描述符类型为<span class="enum">VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</span>，更新描述符时无视<span class="type">VkDescriptorImageInfo</span>::sampler。
    <br>
    <strong>注意，须确保不可变更采样器的生存期不短于描述符布局。</strong>
</p></section>
<section id="descriptorsetlayout">
<h3>封装为descriptorSetLayout类<a class="headerlink" href="#descriptorsetlayout" title="Permalink to this heading"></a></h3>
<p>
    向<span class="path">VKBase.h</span>，vulkan命名空间中添加以下代码：
</p>
<pre class="code">
<span class="kw">class</span> <span class="type">descriptorSetLayout</span> {
    <span class="type">VkDescriptorSetLayout</span> handle = <span class="mcr">VK_NULL_HANDLE</span>;
<span class="kw">public</span>:
    <span class="fn">descriptorSetLayout</span>() = <span class="kw">default</span>;
    <span class="fn">descriptorSetLayout</span>(<span class="type">VkDescriptorSetLayoutCreateInfo</span>&amp; <span class="par">createInfo</span>) {
        <span class="fn">Create</span>(<span class="par">createInfo</span>);
    }
    <span class="fn">descriptorSetLayout</span>(<span class="type">descriptorSetLayout</span>&amp;&amp; <span class="par">other</span>) <span class="kw">noexcept</span> { <span class="mcr">MoveHandle</span>; }
    <span class="fn">~descriptorSetLayout</span>() { <span class="mcr">DestroyHandleBy</span>(<span class="fn">vkDestroyDescriptorSetLayout</span>); }
    <span class="cmt">//Getter</span>
    <span class="mcr">DefineHandleTypeOperator</span>;
    <span class="mcr">DefineAddressFunction</span>;
    <span class="cmt">//Non-const Function</span>
    <span class="type">result_t</span> <span class="fn">Create</span>(<span class="type">VkDescriptorSetLayoutCreateInfo</span>&amp; <span class="par">createInfo</span>) {
        <span class="par">createInfo</span>.sType = <span class="enum">VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO</span>;
        <span class="type">VkResult</span> result = <span class="fn">vkCreateDescriptorSetLayout</span>(<span class="type">graphicsBase</span>::<span class="sfn">Base</span>().<span class="fn">Device</span>(), &amp;<span class="par">createInfo</span>, <span class="kw">nullptr</span>, &amp;handle);
        <span class="kw">if</span> (result)
            outStream &lt;&lt; std::<span class="fn">format</span>(<span class="str">&quot;[ descriptorSetLayout ] ERROR\nFailed to create a descriptor set layout!\nError code: {}\n&quot;</span>, <span class="type">int32_t</span>(result));
        <span class="kw">return</span> result;
    }
};
</pre></section>
</section>
<section id="descriptor-set">
<h2>Descriptor Set<a class="headerlink" href="#descriptor-set" title="Permalink to this heading"></a></h2>
<p>
    描述符集（<span class="type">VkDescriptorSet</span>）顾名思义，是在着色器中被成套使用的一系列描述符的集合。
</p><section id="id3">
<h3>更新描述符集<a class="headerlink" href="#id3" title="Permalink to this heading"></a></h3>
<p>
    用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkUpdateDescriptorSets">vkUpdateDescriptorSets</a>(...)更新描述符集：
</p>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">void</span> <span class="mcr">VKAPI_CALL</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkUpdateDescriptorSets">vkUpdateDescriptorSets</a>(...) 的参数说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDevice</span> device</p></td>
            <td><p>逻辑设备的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> descriptorWriteCount</p></td>
            <td><p><span class="type">VkWriteDescriptorSet</span>的个数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkWriteDescriptorSet</span>* pDescriptorWrites</p></td>
            <td><p>指向<span class="type">VkWriteDescriptorSet</span>的数组，用于指定写入描述符集的操作</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> descriptorCopyCount</p></td>
            <td><p><span class="type">VkCopyDescriptorSet</span>的个数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkCopyDescriptorSet</span>* pDescriptorCopies</p></td>
            <td><p>指向<span class="type">VkCopyDescriptorSet</span>的数组，用于指定复制描述符集的操作</p></td>
        </tr>
    </tbody>
</table>
<p>
    通常应当在录制绑定描述符的命令之前，更新描述符。
    <br>
    自Vulkan1.2起，可在绑定描述符后、提交命令缓冲区前更新描述符，则该描述符集必须从创建时注明了<span class="enum">VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT</span>的描述符池分配，并且创建相应描述符布局时也需要注明<span class="enum">VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT</span>。
</p><section id="id4">
<h4>写入描述符集<a class="headerlink" href="#id4" title="Permalink to this heading"></a></h4>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkWriteDescriptorSet">VkWriteDescriptorSet</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkStructureType</span> sType</p></td>
            <td><p>结构体的类型，本处必须是<span class="enum">VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const void</span>* pNext</p></td>
            <td><p>如有必要，指向一个用于扩展该结构体的结构体</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorSet</span> dstSet</p></td>
            <td><p>需要被更新的描述符集的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> dstBinding</p></td>
            <td><p>指定要更新描述符中的哪个binding</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> dstArrayElement</p></td>
            <td><p>指定从数组中哪个元素开始更新（适用于更新某一类描述符构成的数组的情况）</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> descriptorCount</p></td>
            <td><p>需要更新的描述符的个数（适用于更新某一类描述符构成的数组的情况）</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorType</span> descriptorType</p></td>
            <td><p>描述符的类型</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorImageInfo</span>* pImageInfo</p></td>
            <td><p>若描述符类型是采样器、图像或带采样器的图像，向pImageInfo所指数组填入相关信息，否则为<span class="kw">nullptr</span></p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorBufferInfo</span>* pBufferInfo</p></td>
            <td><p>若描述符类型是uniform或storage缓冲区（或对应的动态缓冲区），向pBufferInfo所指数组填入相关信息，否则为<span class="kw">nullptr</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkBufferView</span>* pTexelBufferView</p></td>
            <td><p>若描述符类型为storage或uniform纹素缓冲区，向pTexelBufferView所指数组填入各个缓冲区视图，否则为<span class="kw">nullptr</span></p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            若描述符类型为内联uniform块，descriptorCount与pNext所指向<a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkWriteDescriptorSetInlineUniformBlock">VkWriteDescriptorSetInlineUniformBlock</a>结构体中的dataSize一致（这似乎有点多此一举？）。
        </p>
    </li>
</ul>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorImageInfo">VkDescriptorImageInfo</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkSampler</span> sampler</p></td>
            <td><p>若描述符类型为采样器或带采样器的图像，在此填入采样器的handle，否则为<span class="mcr">VK_NULL_HANDLE</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkImageView</span> imageView</p></td>
            <td><p>若描述符类型为图像或带采样器的图像或输入附件，在此填入图像视图的handle，否则为<span class="mcr">VK_NULL_HANDLE</span></p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkImageLayout</span> imageLayout</p></td>
            <td><p>若描述符类型为图像或带采样器的图像或输入附件，在此填入图像的内存布局，否则本项被无视</span></p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorBufferInfo">VkDescriptorBufferInfo</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkBuffer</span> buffer</p></td>
            <td><p>缓冲区的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDeviceSize</span> offset</p></td>
            <td><p>在着色器中访问缓冲区时的起始点，对应Vulkan的缓冲区中，距离缓冲区起始位置的距离（即用来定义一个映射关系）</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDeviceSize</span> range</p></td>
            <td><p>可通过该描述符访问的缓冲区的大小范围，若使用特殊值<span class="mcr">VK_WHOLE_SIZE</span>，则为从offset到缓冲区末尾的全部范围</p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            这里的offset旨在使用描述符前，定义一个映射关系。动态uniform缓冲区或动态storage缓冲区的动态offset是在用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkCmdBindDescriptorSets">vkCmdBindDescriptorSets</a>(...)绑定描述符时指定的，最终着色器中访问动态缓冲区时的起始点，由这两个offset之合确定。
        </p>
    </li>
    <li>
        <p>
            若多个描述符想引用同一个缓冲区中的不同部分，需满足对齐要求：若提供的缓冲区类型是uniform缓冲区/动态uniform缓冲区，则offset必须为<a href="https://renderdoc.org/vkspec_chunked/chap5.html#VkPhysicalDeviceProperties">VkPhysicalDeviceProperties</a>::limits::minUniformBufferOffsetAlignment的整数倍。相应地，若提供的缓冲区类型是storage缓冲区/动态storage缓冲区，则offset必须为<a href="https://renderdoc.org/vkspec_chunked/chap5.html#VkPhysicalDeviceProperties">VkPhysicalDeviceProperties</a>::limits::minStorageBufferOffsetAlignment的整数倍。
        </p>
    </li>
</ul></section>
<section id="id5">
<h4>复制描述符集<a class="headerlink" href="#id5" title="Permalink to this heading"></a></h4>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkCopyDescriptorSet">VkCopyDescriptorSet</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkStructureType</span> sType</p></td>
            <td><p>结构体的类型，本处必须是<span class="enum">VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const void</span>* pNext</p></td>
            <td><p>如有必要，指向一个用于扩展该结构体的结构体</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorSet</span> srcSet</p></td>
            <td><p>源描述符集的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> srcBinding</p></td>
            <td><p>指定从源描述符集中的哪个binding复制</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> srcArrayElement</p></td>
            <td><p>指定从源描述符集的数组中哪个元素开始复制（适用于更新某一类描述符构成的数组的情况）</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDescriptorSet</span> dstSet</p></td>
            <td><p>目标描述符集的handle</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> dstBinding</p></td>
            <td><p>指定复制到目标描述符集中的哪个binding</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> dstArrayElement</p></td>
            <td><p>指定复制到目标描述符集的数组中的起始位置（适用于更新某一类描述符构成的数组的情况）</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> descriptorCount</p></td>
            <td><p>需要复制的描述符的个数（适用于更新某一类描述符构成的数组的情况）</p></td>
        </tr>
    </tbody>
</table></section>
</section>
<section id="descriptorset">
<h3>封装为descriptorSet类<a class="headerlink" href="#descriptorset" title="Permalink to this heading"></a></h3>
<p>
    向<span class="path">VKBase.h</span>，vulkan命名空间中添加以下代码：
</p>
<pre class="code">
<span class="kw">class</span> <span class="type">descriptorSet</span> {
    <span class="kw">friend class</span> <span class="type">descriptorPool</span>;
    <span class="type">VkDescriptorSet</span> handle = <span class="mcr">VK_NULL_HANDLE</span>;
<span class="kw">public</span>:
    <span class="fn">descriptorSet</span>() = <span class="kw">default</span>;
    <span class="fn">descriptorSet</span>(<span class="type">descriptorSet</span>&amp;&amp; <span class="par">other</span>) <span class="kw">noexcept</span> { <span class="mcr">MoveHandle</span>; }
    <span class="cmt">//Getter</span>
    <span class="mcr">DefineHandleTypeOperator</span>;
    <span class="mcr">DefineAddressFunction</span>;
    <span class="cmt">//Const Function</span>
    <span class="kw">void</span> <span class="fn">Write</span>(<span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorImageInfo</span>&gt; <span class="par">descriptorInfos</span>, <span class="type">VkDescriptorType</span> <span class="par">descriptorType</span>, <span class="type">uint32_t</span> <span class="par">dstBinding</span> = 0, <span class="type">uint32_t</span> <span class="par">dstArrayElement</span> = 0) <span class="kw">const</span> {
        <span class="type">VkWriteDescriptorSet</span> writeDescriptorSet = {
            .dstSet = handle,
            .dstBinding = <span class="par">dstBinding</span>,
            .dstArrayElement = <span class="par">dstArrayElement</span>,
            .descriptorCount = <span class="type">uint32_t</span>(<span class="par">descriptorInfos</span>.<span class="fn">Count</span>()),
            .descriptorType = <span class="par">descriptorType</span>,
            .pImageInfo = <span class="par">descriptorInfos</span>.<span class="fn">Pointer</span>()
        };
        <span class="sfn">Update</span>(writeDescriptorSet);
    }
    <span class="kw">void</span> <span class="fn">Write</span>(<span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorBufferInfo</span>&gt; <span class="par">descriptorInfos</span>, <span class="type">VkDescriptorType</span> <span class="par">descriptorType</span>, <span class="type">uint32_t</span> <span class="par">dstBinding</span> = 0, <span class="type">uint32_t</span> <span class="par">dstArrayElement</span> = 0) <span class="kw">const</span> {
        <span class="type">VkWriteDescriptorSet</span> writeDescriptorSet = {
            .dstSet = handle,
            .dstBinding = <span class="par">dstBinding</span>,
            .dstArrayElement = <span class="par">dstArrayElement</span>,
            .descriptorCount = <span class="type">uint32_t</span>(<span class="par">descriptorInfos</span>.<span class="fn">Count</span>()),
            .descriptorType = <span class="par">descriptorType</span>,
            .pBufferInfo = <span class="par">descriptorInfos</span>.<span class="fn">Pointer</span>()
        };
        <span class="sfn">Update</span>(writeDescriptorSet);
    }
    <span class="kw">void</span> <span class="fn">Write</span>(<span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkBufferView</span>&gt; <span class="par">descriptorInfos</span>, <span class="type">VkDescriptorType</span> <span class="par">descriptorType</span>, <span class="type">uint32_t</span> <span class="par">dstBinding</span> = 0, <span class="type">uint32_t</span> <span class="par">dstArrayElement</span> = 0) <span class="kw">const</span> {
        <span class="type">VkWriteDescriptorSet</span> writeDescriptorSet = {
            .dstSet = handle,
            .dstBinding = <span class="par">dstBinding</span>,
            .dstArrayElement = <span class="par">dstArrayElement</span>,
            .descriptorCount = <span class="type">uint32_t</span>(<span class="par">descriptorInfos</span>.<span class="fn">Count</span>()),
            .descriptorType = <span class="par">descriptorType</span>,
            .pTexelBufferInfo = <span class="par">descriptorInfos</span>.<span class="fn">Pointer</span>()
        };
        <span class="sfn">Update</span>(writeDescriptorSet);
    }
    <span class="kw">void</span> <span class="fn">Write</span>(<span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">bufferView</span>&gt; <span class="par">descriptorInfos</span>, <span class="type">VkDescriptorType</span> <span class="par">descriptorType</span>, <span class="type">uint32_t</span> <span class="par">dstBinding</span> = 0, <span class="type">uint32_t</span> <span class="par">dstArrayElement</span> = 0) <span class="kw">const</span> {
        <span class="fn">Write</span>({ <span class="par">descriptorInfos</span>[0].<span class="fn">Address</span>(), <span class="par">descriptorInfos</span>.<span class="fn">Count</span>() }, <span class="par">descriptorType</span>, <span class="par">dstBinding</span>, <span class="par">dstArrayElement</span>);
    }
    <span class="cmt">//Static Function</span>
    <span class="kw">static void</span> <span class="sfn">Update</span>(<span class="type">arrayRef</span>&lt;<span class="type">VkWriteDescriptorSet</span>&gt; <span class="par">writes</span>, <span class="type">arrayRef</span>&lt;<span class="type">VkCopyDescriptorSet</span>&gt; <span class="par">copies</span> = {}) {
        <span class="kw">for</span> (<span class="kw">auto</span>&amp; i : <span class="par">writes</span>)
            i.sType = <span class="enum">VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET</span>;
        <span class="kw">for</span> (<span class="kw">auto</span>&amp; i : <span class="par">copies</span>)
            i.sType = <span class="enum">VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET</span>;
        <span class="fn">vkUpdateDescriptorSets</span>(<span class="type">graphicsBase</span>::<span class="sfn">Base</span>().<span class="fn">Device</span>(), <span class="par">writes</span>.<span class="fn">Count</span>(), <span class="par">writes</span>.<span class="fn">Pointer</span>(), <span class="par">copies</span>.<span class="fn">Count</span>(), <span class="par">copies</span>.<span class="fn">Pointer</span>());
    }
};
</pre></section>
</section>
<section id="descriptor-pool">
<h2>Descriptor Pool<a class="headerlink" href="#descriptor-pool" title="Permalink to this heading"></a></h2>
<p>
   描述符池（<span class="type">VkDescriptorPool</span>）用于分配描述符集。
</p><section id="id6">
<h3>创建描述符池<a class="headerlink" href="#id6" title="Permalink to this heading"></a></h3>
<p>
    用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkCreateDescriptorPool">vkCreateDescriptorPool</a>(...)创建描述符池：
</p>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="type">VkResult</span> <span class="mcr">VKAPI_CALL</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkCreateDescriptorPool">vkCreateDescriptorPool</a>(...) 的参数说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDevice</span> device</p></td>
            <td><p>逻辑设备的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorPoolCreateInfo</span>* pCreateInfo</p></td>
            <td><p>指向<span class="type">VkDescriptorSetLayout</span>的创建信息</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkAllocationCallbacks</span>* pAllocator</p></td>
            <td><p></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDescriptorPool</span>* pDescriptorPool</p></td>
            <td><p>若执行成功，将描述符池的handle写入*pDescriptorPool</p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorPoolCreateInfo">VkDescriptorPoolCreateInfo</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkStructureType</span> sType</p></td>
            <td><p>结构体的类型，本处必须是<span class="enum">VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const void</span>* pNext</p></td>
            <td><p>如有必要，指向一个用于扩展该结构体的结构体</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorPoolCreateFlags</span> flags</p></td>
            <td><p>见后文</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> maxSets</p></td>
            <td><p>该描述符池所能分配的描述符集的最大个数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> poolSizeCount</p></td>
            <td><p><span class="type">VkDescriptorPoolSize</span>的个数</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorPoolSize</span>* pPoolSizes</p></td>
            <td><p>指向<span class="type">VkDescriptorPoolSize</span>的数组，用于指定所需的各种描述符的个数</p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col>
        <col>
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head"><p>版本要求</p></th>
            <th class="head"><p><a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorPoolCreateFlagBits">VkDescriptorPoolCreateFlagBits</a> 的枚举项</p></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><p>1.0</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT </span>表示可以释放从描述符池中分配的描述符集，资源会被返还到描述符池中</p></td>
        </tr>
        <tr>
            <td><p>1.2</p></td>
            <td><p><span class="enum">VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT   </span>如前文所述，表示从该描述符池分配的描述符集，可以在被绑定后、提交命令缓冲区前被更新</p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorPoolSize">VkDescriptorPoolSize</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorType</span> type</p></td>
            <td><p>描述符的类型</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> descriptorCount</p></td>
            <td><p>所需该种描述符的个数</p></td>
        </tr>
    </tbody>
</table></section>
<section id="id7">
<h3>分配描述符集<a class="headerlink" href="#id7" title="Permalink to this heading"></a></h3>
<p>
    用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkAllocateDescriptorSets">vkAllocateDescriptorSets</a>(...)分配描述符集：
</p>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="type">VkResult</span> <span class="mcr">VKAPI_CALL</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkAllocateDescriptorSets">vkAllocateDescriptorSets</a>(...) 的参数说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDevice</span> device</p></td>
            <td><p>逻辑设备的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorSetAllocateInfo</span>* pAllocateInfo</p></td>
            <td><p>指向<span class="type">VkDescriptorSet</span>的分配信息</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorSet</span>* pDescriptorSet</p></td>
            <td><p>若执行成功，将描述符集的handle写入pDescriptorSets所指数组</p></td>
        </tr>
    </tbody>
</table>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="kw">struct</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#VkDescriptorSetAllocateInfo">VkDescriptorSetAllocateInfo</a> 的成员说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkStructureType</span> sType</p></td>
            <td><p>结构体的类型，本处必须是<span class="enum">VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO</span></p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const void</span>* pNext</p></td>
            <td><p>如有必要，指向一个用于扩展该结构体的结构体</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">VkDescriptorPool</span> descriptorPool</p></td>
            <td><p>描述符池的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">uint32_t</span> descriptorSetCount</p></td>
            <td><p>所需分配的描述符集的个数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorSetLayout</span>* pSetLayouts</p></td>
            <td><p>所需分配的各个描述符集对应的描述符布局</p></td>
        </tr>
    </tbody>
</table></section>
<section id="id8">
<h3>释放描述符集<a class="headerlink" href="#id8" title="Permalink to this heading"></a></h3>
<p>
    用<a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkFreeDescriptorSets">vkFreeDescriptorSets</a>(...)释放描述符集：
</p>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p><span class="type">VkResult</span> <span class="mcr">VKAPI_CALL</span> <a href="https://renderdoc.org/vkspec_chunked/chap14.html#vkFreeDescriptorSets">vkFreeDescriptorSets</a> 的参数说明</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">VkDevice</span> device</p></td>
            <td><p>逻辑设备的handle</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="type">VkDescriptorPool</span> descriptorPool</p></td>
            <td><p>描述符池的handle</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">uint32_t</span> descriptorSetCount</p></td>
            <td><p>所需释放的描述符集的个数</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">const</span> <span class="type">VkDescriptorSet</span>* pDescriptorSets</p></td>
            <td><p>指向由所需释放的描述符集的handle构成的数组</p></td>
        </tr>
    </tbody>
</table>
<ul>
    <li>
        <p>
            该函数只会返回<span class="enum">VK_SUCCESS</span>。
        </p>
    </li>
</ul></section>
<section id="descriptorpool">
<h3>封装为descriptorPool类<a class="headerlink" href="#descriptorpool" title="Permalink to this heading"></a></h3>
<p>
    向<span class="path">VKBase.h</span>，vulkan命名空间中，<span class="type">descriptorSet</span>的定义后添加以下代码：
</p>
<pre class="code">
<span class="kw">class</span> <span class="type">descriptorPool</span> {
    <span class="type">VkDescriptorPool</span> handle = <span class="mcr">VK_NULL_HANDLE</span>;
<span class="kw">public</span>:
    <span class="fn">descriptorPool</span>() = <span class="kw">default</span>;
    <span class="fn">descriptorPool</span>(<span class="type">VkDescriptorPoolCreateInfo</span>&amp; <span class="par">createInfo</span>) {
        <span class="fn">Create</span>(<span class="par">createInfo</span>);
    }
    <span class="fn">descriptorPool</span>(<span class="type">uint32_t</span> <span class="par">maxSetCount</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorPoolSize</span>&gt; <span class="par">poolSizes</span>, <span class="type">VkDescriptorPoolCreateFlags</span> <span class="par">flags</span> = 0) {
        <span class="fn">Create</span>(<span class="par">maxSetCount</span>, <span class="par">poolSizes</span>, <span class="par">flags</span>);
    }
    <span class="fn">descriptorPool</span>(<span class="type">descriptorPool</span>&amp;&amp; <span class="par">other</span>) <span class="kw">noexcept</span> { <span class="mcr">MoveHandle</span>; }
    <span class="fn">~descriptorPool</span>() { <span class="mcr">DestroyHandleBy</span>(<span class="fn">vkDestroyDescriptorPool</span>); }
    <span class="cmt">//Getter</span>
    <span class="mcr">DefineHandleTypeOperator</span>;
    <span class="mcr">DefineAddressFunction</span>;
    <span class="cmt">//Const Function</span>
    <span class="type">result_t</span> <span class="fn">AllocateSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">VkDescriptorSet</span>&gt; <span class="par">sets</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorSetLayout</span>&gt; <span class="par">setLayouts</span>) <span class="kw">const</span> {
        <span class="kw">if</span> (<span class="par">sets</span>.<span class="fn">Count</span>() != <span class="par">setLayouts</span>.<span class="fn">Count</span>())
            <span class="kw">if</span> (<span class="par">sets</span>.<span class="fn">Count</span>() &lt; <span class="par">setLayouts</span>.<span class="fn">Count</span>()) {
                outStream &lt;&lt; std::<span class="fn">format</span>(<span class="str">&quot;[ descriptorPool ] ERROR\nFor each descriptor set, must provide a corresponding layout!\n&quot;</span>);
                <span class="kw">return</span> <span class="enum">VK_RESULT_MAX_ENUM</span>; <span class="cmt">//没有合适的错误代码，别用VK_ERROR_UNKNOWN</span>
            }
            <span class="kw">else</span>
                outStream &lt;&lt; std::<span class="fn">format</span>(<span class="str">&quot;[ descriptorPool ] WARNING\nProvided layouts are more than sets!\n&quot;</span>);
        <span class="type">VkDescriptorSetAllocateInfo</span> allocateInfo = {
            .sType = <span class="enum">VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO</span>,
            .descriptorPool = handle,
            .descriptorSetCount = <span class="type">uint32_t</span>(<span class="par">sets</span>.<span class="fn">Count</span>()),
            .pSetLayouts = <span class="par">setLayouts</span>.<span class="fn">Pointer</span>()
        };
        <span class="type">VkResult</span> result = <span class="fn">vkAllocateDescriptorSets</span>(<span class="type">graphicsBase</span>::<span class="sfn">Base</span>().<span class="fn">Device</span>(), &amp;allocateInfo, <span class="par">sets</span>.<span class="fn">Pointer</span>());
        <span class="kw">if</span> (result)
            outStream &lt;&lt; std::<span class="fn">format</span>(<span class="str">&quot;[ descriptorPool ] ERROR\nFailed to allocate descriptor sets!\nError code: {}\n&quot;</span>, <span class="type">int32_t</span>(result));
        <span class="kw">return</span> result;
    }
    <span class="type">result_t</span> <span class="fn">AllocateSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">VkDescriptorSet</span>&gt; <span class="par">sets</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">descriptorSetLayout</span>&gt; <span class="par">setLayouts</span>) <span class="kw">const</span> {
        <span class="kw">return</span> <span class="fn">AllocateSets</span>(
            <span class="par">sets</span>,
            { <span class="par">setLayouts</span>[0].<span class="fn">Address</span>(), <span class="par">setLayouts</span>.<span class="fn">Count</span>() });
    }
    <span class="type">result_t</span> <span class="fn">AllocateSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">descriptorSet</span>&gt; <span class="par">sets</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorSetLayout</span>&gt; <span class="par">setLayouts</span>) <span class="kw">const</span> {
        <span class="kw">return</span> <span class="fn">AllocateSets</span>(
            { &amp;<span class="par">sets</span>[0].handle, <span class="par">sets</span>.<span class="fn">Count</span>() },
            <span class="par">setLayouts</span>);
    }
    <span class="type">result_t</span> <span class="fn">AllocateSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">descriptorSet</span>&gt; <span class="par">sets</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">descriptorSetLayout</span>&gt; <span class="par">setLayouts</span>) <span class="kw">const</span> {
        <span class="kw">return</span> <span class="fn">AllocateSets</span>(
            { &amp;<span class="par">sets</span>[0].handle, <span class="par">sets</span>.<span class="fn">Count</span>() },
            { <span class="par">setLayouts</span>[0].<span class="fn">Address</span>(), <span class="par">setLayouts</span>.<span class="fn">Count</span>() });
    }
    <span class="type">result_t</span> <span class="fn">FreeSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">VkDescriptorSet</span>&gt; <span class="par">sets</span>) <span class="kw">const</span> {
        <span class="type">VkResult</span> result = <span class="fn">vkFreeDescriptorSets</span>(<span class="type">graphicsBase</span>::<span class="sfn">Base</span>().<span class="fn">Device</span>(), handle, <span class="par">sets</span>.<span class="fn">Count</span>(), <span class="par">sets</span>.<span class="fn">Pointer</span>());
        <span class="fn">memset</span>(<span class="par">sets</span>.<span class="fn">Pointer</span>(), 0, <span class="par">sets</span>.<span class="fn">Count</span>() * <span class="kw">sizeof</span>(<span class="type">VkDescriptorSet</span>));
        <span class="kw">return</span> result; <span class="cmt">//Though vkFreeDescriptorSets(...) can only return VK_SUCCESS</span>
    }
    <span class="type">result_t</span> <span class="fn">FreeSets</span>(<span class="type">arrayRef</span>&lt;<span class="type">descriptorSet</span>&gt; <span class="par">sets</span>) <span class="kw">const</span> {
        <span class="kw">return</span> <span class="fn">FreeSets</span>({ &amp;<span class="par">sets</span>[0].handle, <span class="par">sets</span>.<span class="fn">Count</span>() });
    }
    <span class="cmt">//Non-const Function</span>
    <span class="type">result_t</span> <span class="fn">Create</span>(<span class="type">VkDescriptorPoolCreateInfo</span>&amp; <span class="par">createInfo</span>) {
        <span class="par">createInfo</span>.sType = <span class="type">VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO</span>;
        <span class="type">VkResult</span> result = <span class="fn">vkCreateDescriptorPool</span>(<span class="type">graphicsBase</span>::<span class="sfn">Base</span>().<span class="fn">Device</span>(), &amp;<span class="par">createInfo</span>, <span class="kw">nullptr</span>, &amp;handle);
        <span class="kw">if</span> (result)
            outStream &lt;&lt; std::<span class="fn">format</span>(<span class="str">&quot;[ descriptorPool ] ERROR\nFailed to create a descriptor pool!\nError code: {}\n&quot;</span>, <span class="type">int32_t</span>(result));
        <span class="kw">return</span> result;
    }
    <span class="type">result_t</span> <span class="fn">Create</span>(<span class="type">uint32_t</span> <span class="par">maxSetCount</span>, <span class="type">arrayRef</span>&lt;<span class="kw">const</span> <span class="type">VkDescriptorPoolSize</span>&gt; <span class="par">poolSizes</span>, <span class="type">VkDescriptorPoolCreateFlags</span> <span class="par">flags</span> = 0) {
        <span class="type">VkDescriptorPoolCreateInfo</span> createInfo = {
            .flags = <span class="par">flags</span>,
            .maxSets = <span class="par">maxSetCount</span>,
            .poolSizeCount = <span class="type">uint32_t</span>(<span class="par">poolSizes</span>.<span class="fn">Count</span>()),
            .pPoolSizes = <span class="par">poolSizes</span>.<span class="fn">Pointer</span>()
        };
        <span class="kw">return</span> <span class="fn">Create</span>(createInfo);
    }
};
</pre></section>
</section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="Ch3-5%20%E5%91%BD%E4%BB%A4%E7%BC%93%E5%86%B2%E5%8C%BA.html" class="btn btn-neutral float-left" title="Ch3-5 命令缓冲区" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> 上一页</a>
        <a href="Ch3-7%20%E9%87%87%E6%A0%B7%E5%99%A8.html" class="btn btn-neutral float-right" title="Ch3-7 采样器" accesskey="n" rel="next">下一页 <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; 版权所有 2021-2025, 葉橙.</p>
  </div>

  利用 <a href="https://www.sphinx-doc.org/">Sphinx</a> 构建，使用了 
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">主题</a>
    由 <a href="https://readthedocs.org">Read the Docs</a>开发.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>